using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;

namespace ClownFish
{
    public class DbContext : IDisposable
    {
        [CompilerGenerated]
        private sealed class Class5
        {
            public DbContext dbContext_0;

            public string[] string_0;

            public DataSet method_0()
            {
                DataSet result;
                using (DbDataReader dbDataReader = this.dbContext_0.dbCommand_0.ExecuteReader(CommandBehavior.Default))
                {
                    DataSet dataSet = new DataSet();
                    dataSet.Load(dbDataReader, LoadOption.PreserveChanges, this.string_0);
                    dbDataReader.Close();
                    result = dataSet;
                }
                return result;
            }
        }

        public static readonly string STR_PageIndex = "PageIndex";

        public static readonly string STR_PageSize = "PageSize";

        public static readonly string STR_TotalRecords = "TotalRecords";

        private static string string_0;
        public static int DBConnectCount;

        private DbConnection dbConnection_0;

        private DbTransaction dbTransaction_0;

        private DbCommand dbCommand_0;

        private bool IsError;

        private string string_1;

        internal int ListIniCapacity;

        internal Class25 class25_0;

        private bool UseTransaction;

        private static DbContextExceptionHandler _ExceptionEvent;

        private static DbContextEventHandler _BeforeExecuteEvent;

        private static DbContextEventHandler _AfterExecuteEvent;

        private static DbContextEventHandler _OpenConnectionEvent;

        internal static readonly char[] char_0 = new char[]
        {
            '@',
            '?',
            ':',
            '_',
            '#',
            '$'
        };

        [CompilerGenerated]
        private bool bool_2;

        [CompilerGenerated]
        private object object_0;

        [CompilerGenerated]
        private bool bool_3;

        [CompilerGenerated]
        //private XmlCommand xmlCommand_0;


        public static event DbContextExceptionHandler OnException
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            add
            {
                DbContext._ExceptionEvent = (DbContextExceptionHandler)Delegate.Combine(DbContext._ExceptionEvent, value);
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            remove
            {
                DbContext._ExceptionEvent = (DbContextExceptionHandler)Delegate.Remove(DbContext._ExceptionEvent, value);
            }
        }

        public static event DbContextEventHandler OnBeforeExecute
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            add
            {
                DbContext._BeforeExecuteEvent = (DbContextEventHandler)Delegate.Combine(DbContext._BeforeExecuteEvent, value);
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            remove
            {
                DbContext._BeforeExecuteEvent = (DbContextEventHandler)Delegate.Remove(DbContext._BeforeExecuteEvent, value);
            }
        }

        public static event DbContextEventHandler OnAfterExecute
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            add
            {
                DbContext._AfterExecuteEvent = (DbContextEventHandler)Delegate.Combine(DbContext._AfterExecuteEvent, value);
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            remove
            {
                DbContext._AfterExecuteEvent = (DbContextEventHandler)Delegate.Remove(DbContext._AfterExecuteEvent, value);
            }
        }

        public static event DbContextEventHandler OnOpenConnection
        {
            [MethodImpl(MethodImplOptions.Synchronized)]
            add
            {
                DbContext._OpenConnectionEvent = (DbContextEventHandler)Delegate.Combine(DbContext._OpenConnectionEvent, value);
            }
            [MethodImpl(MethodImplOptions.Synchronized)]
            remove
            {
                DbContext._OpenConnectionEvent = (DbContextEventHandler)Delegate.Remove(DbContext._OpenConnectionEvent, value);
            }
        }

        public DbConnection Connection
        {
            get
            {
                return this.dbConnection_0;
            }
        }

        public DbTransaction Transaction
        {
            get
            {
                return this.dbTransaction_0;
            }
        }

        public DbCommand CurrentCommand
        {
            get
            {
                return this.dbCommand_0;
            }
        }

        public bool KeepConnectionOnException
        {
            get;
            set;
        }

        public object Tag
        {
            get;
            set;
        }

        public string ParamNamePrefix
        {
            get
            {
                return this.string_1;
            }
        }

        public bool AutoRetrieveOutputValues
        {
            get;
            set;
        }
        /*
        public XmlCommand CurrentXmlCommand
        {
            get;
            private set;
        }
        */
        public bool IgnoreErrorEvent
        {
            get;
            set;
        }

        public static void RegisterDbConnectionInfo(string configName, string providerName, string cmdParamNamePrefix, string defaultConnString)
        {
            if (string.IsNullOrEmpty(defaultConnString))
            {
                throw new ArgumentNullException("defaultConnString");
            }
            DbContext.smethod_0(configName, providerName, cmdParamNamePrefix, defaultConnString, null);
        }

        public static void RegisterDbConnectionInfo(string configName, string providerName, string cmdParamNamePrefix, Func<string, string> obtainFunc)
        {
            if (obtainFunc == null)
            {
                throw new ArgumentNullException("obtainFunc");
            }
            DbContext.smethod_0(configName, providerName, cmdParamNamePrefix, null, obtainFunc);
        }

        private static void smethod_0(string string_2, string string_3, string string_4, string string_5, Func<string, string> func_0)
        {
            if (string.IsNullOrEmpty(string_2))
            {
                throw new ArgumentNullException("configName");
            }
            if (string.IsNullOrEmpty(string_3))
            {
                throw new ArgumentNullException("providerName");
            }
            Class23.smethod_0(string_2, string_3, string_4, string_5, func_0);
            if (string.IsNullOrEmpty(DbContext.string_0))
            {
                DbContext.string_0 = string_2;
            }
        }

        private static string smethod_1()
        {
            return DbContext.string_0;
        }

        public DbContext(bool useTransaction) : this(DbContext.smethod_1(), null, useTransaction)
        {
        }

        public DbContext(string configName) : this(configName, null, false)
        {
        }

        public DbContext(string configName, bool useTransaction) : this(configName, null, useTransaction)
        {
        }

        public DbContext(string configName, string connectionString, bool useTransaction)
        {
            if (string.IsNullOrEmpty(configName))
            {
                throw new ArgumentNullException("configName");
            }
            Class22 @class = Class23.smethod_1(configName);
            if (@class == null)
            {
                throw new InvalidOperationException(string.Format("配置项: [{0}] 不存在。", configName));
            }
            this.dbConnection_0 = @class.dbProviderFactory_0.CreateConnection();


            this.string_1 = @class.string_1;
            if (string.IsNullOrEmpty(connectionString))
            {
                if (@class.func_0 != null)
                {
                    this.dbConnection_0.ConnectionString = @class.func_0(configName);
                }
                else
                {
                    this.dbConnection_0.ConnectionString = @class.string_2;
                }
            }
            else
            {
                this.dbConnection_0.ConnectionString = connectionString;
            }
            if (string.IsNullOrEmpty(this.dbConnection_0.ConnectionString))
            {
                throw new ArgumentNullException("connectionString");
            }
            this.UseTransaction = useTransaction;
            this.AutoRetrieveOutputValues = DbContextDefaultSetting.AutoRetrieveOutputValues;
            this.ListIniCapacity = DbContextDefaultSetting.ListResultCapacity;
        }

        public DbCommand CreateCommand(string sqlOrName, CommandType commandType)
        {
            //WriteLog("CommandText:" + sqlOrName);
            this.method_4();
            DbCommand dbCommand = this.dbConnection_0.CreateCommand();
            dbCommand.CommandText = sqlOrName;
            dbCommand.CommandType = commandType;

            this.dbCommand_0 = dbCommand;
            //this.CurrentXmlCommand = null;
            return dbCommand;
        }
        /*
        public DbCommand CreateXmlCommand(string commandName)
        {
            if (string.IsNullOrEmpty(commandName))
            {
                throw new ArgumentNullException("commandName");
            }
            XmlCommand command = XmlCommandManager.GetCommand(commandName);
            if (command == null)
            {
                throw new ArgumentOutOfRangeException("commandName");
            }
            return this.method_0(command, commandName);
        }

        internal DbCommand method_0(XmlCommand xmlCommand_1, string string_2)
        {
            if (xmlCommand_1 == null)
            {
                throw new ArgumentNullException("name");
            }
            DbCommand dbCommand = this.CreateCommand(xmlCommand_1.CommandText, xmlCommand_1.CommandType);
            dbCommand.CommandTimeout = xmlCommand_1.Timeout;
            this.CurrentXmlCommand = xmlCommand_1;
            DbParameter[] values = xmlCommand_1.smethod_4(dbCommand);
            dbCommand.Parameters.AddRange(values);
            return dbCommand;
        }
        */
        public void CommitTransaction()
        {
            this.method_6();
            this.dbTransaction_0.Commit();
        }

        private void method_1()
        {
            if (this.dbConnection_0 != null)
            {
                try
                {
                    if (this.dbConnection_0.State == ConnectionState.Open)
                    {
                        this.dbConnection_0.Close();
                        System.Threading.Interlocked.Decrement(ref DBConnectCount);
                        //WriteLog("DBConnectCount:" + DBConnectCount.ToString());
                    }

                    this.dbConnection_0.Dispose();
                }
                catch
                {
                }
                finally
                {
                    this.dbConnection_0 = null;

                }


            }
        }

        private void method_2()
        {
            if (this.dbTransaction_0 == null)
            {
                return;
            }
            try
            {
                this.dbTransaction_0.Rollback();
            }
            catch
            {
            }
            finally
            {
                this.dbTransaction_0 = null;
            }
        }

        public void Dispose()
        {
            //WriteLog("Dispose()");
            this.method_1();
            this.method_3();
        }

        private void method_3()
        {
            if (this.dbTransaction_0 != null)
            {
                try
                {
                    this.dbTransaction_0.Dispose();
                }
                catch
                {
                }
                finally
                {
                    this.dbTransaction_0 = null;
                }
            }
        }

        private void method_4()
        {
            if (this.dbConnection_0 == null)
            {
                throw new InvalidOperationException("connection is null.");
            }
        }

        private void Assertion_DBCommand()
        {
            if (this.dbCommand_0 == null)
            {
                throw new InvalidOperationException("command is null.");
            }
        }

        private void method_6()
        {
            if (this.dbTransaction_0 == null)
            {
                throw new InvalidOperationException("transcation is null.");
            }
        }

        private T ConnnectDB<T>(Func<T> func_0)
        {
            this.Assertion_DBCommand();
            if (this.dbConnection_0.State != ConnectionState.Open)
            {
                this.dbConnection_0.Open();
                System.Threading.Interlocked.Increment(ref DBConnectCount);
                //WriteLog("DBConnectCount:" + DBConnectCount.ToString());
                this.fireOpenConnectionEvent();
            }
            if (this.UseTransaction)
            {
                if (this.dbTransaction_0 == null)
                {
                    this.dbTransaction_0 = this.dbConnection_0.BeginTransaction();
                }
                if (this.dbCommand_0.Transaction == null)
                {
                    this.dbCommand_0.Transaction = this.dbTransaction_0;
                }
            }
            this.fireBeforeExecuteEvent();
            T result;
            try
            {
                //if (this.CurrentXmlCommand != null && !string.IsNullOrEmpty(this.CurrentXmlCommand.Database) && string.Compare(this.CurrentXmlCommand.Database, this.dbConnection_0.Database, true) != 0)
                //{
                //    this.dbConnection_0.ChangeDatabase(this.CurrentXmlCommand.Database);
                //}
                result = func_0();
            }
            catch (Exception exception_)
            {
                this.method_8(exception_);
                throw;
            }
            finally
            {
                this.fireAfterExecuteEvent();
            }
            return result;
        }

        private void method_8(Exception exception_0)
        {
            if (!this.KeepConnectionOnException)
            {
                //WriteLog("method_8");
                this.method_2();
                this.method_1();
            }
            this.IsError = true;
            if (!this.IgnoreErrorEvent)
            {
                DbContextExceptionHandler dbContextExceptionHandler = DbContext._ExceptionEvent;
                if (dbContextExceptionHandler != null)
                {
                    dbContextExceptionHandler(this, exception_0);
                }
            }
        }

        private void fireOpenConnectionEvent()
        {
            DbContextEventHandler dbContextEventHandler = DbContext._OpenConnectionEvent;
            if (dbContextEventHandler != null)
            {
                dbContextEventHandler(this);
            }
        }

        private void fireBeforeExecuteEvent()
        {
            DbContextEventHandler dbContextEventHandler = DbContext._BeforeExecuteEvent;
            if (dbContextEventHandler != null)
            {
                dbContextEventHandler(this);
            }
        }

        private void fireAfterExecuteEvent()
        {
            if (this.IsError)
            {
                return;
            }
            DbContextEventHandler dbContextEventHandler = DbContext._AfterExecuteEvent;
            if (dbContextEventHandler != null)
            {
                dbContextEventHandler(this);
            }
            if (this.class25_0 != null)
            {
                DbHelper.smethod_1(this);
                this.class25_0 = null;

            }
        }

        public void AddParameterWithValue(string paraName, object paraValue)
        {
            DbParameter dbParameter = this.dbCommand_0.CreateParameter();
            dbParameter.ParameterName = this.string_1 + paraName;
            dbParameter.Value = paraValue;
            this.CurrentCommand.Parameters.Add(dbParameter);
        }

        public DbParameter AddParameter(string paraName, object paraValue, DbType paraType)
        {
            return this.AddParameter(paraName, paraValue, paraType, null, ParameterDirection.Input);
        }

        public DbParameter AddParameter(string paraName, object paraValue, DbType paraType, int size)
        {
            return this.AddParameter(paraName, paraValue, paraType, new int?(size), ParameterDirection.Input);
        }

        public DbParameter AddParameter(string paraName, object paraValue, DbType paraType, int? size, ParameterDirection inout)
        {
            this.Assertion_DBCommand();
            DbParameter dbParameter = this.dbCommand_0.CreateParameter();
            dbParameter.ParameterName = this.string_1 + paraName;
            dbParameter.DbType = paraType;
            dbParameter.Direction = inout;
            if (size.HasValue)
            {
                dbParameter.Size = size.Value;
            }
            if (paraValue != null)
            {
                dbParameter.Value = paraValue;
            }
            this.dbCommand_0.Parameters.Add(dbParameter);
            return dbParameter;
        }

        public DbParameter GetCommandParameter(string parameterName)
        {
            if (string.IsNullOrEmpty(parameterName))
            {
                throw new ArgumentNullException("parameterName");
            }
            this.Assertion_DBCommand();
            parameterName = this.ParamNamePrefix + parameterName;
            DbParameterCollection parameters = this.CurrentCommand.Parameters;
            int num = parameters.IndexOf(parameterName);
            if (num >= 0)
            {
                return parameters[num];
            }
            foreach (DbParameter dbParameter in parameters)
            {
                if (dbParameter.ParameterName.EndsWith(parameterName) && dbParameter.ParameterName.Length == parameterName.Length + 1 && Array.IndexOf<char>(DbContext.char_0, dbParameter.ParameterName[0]) >= 0)
                {
                    return dbParameter;
                }
            }
            return null;
        }

        public int ExecuteNonQuery()
        {
            return this.ConnnectDB<int>(new Func<int>(this.method_12));
        }

        public object ExecuteScalar()
        {
            return this.ConnnectDB<object>(new Func<object>(this.method_13));
        }


        /// <summary>
        /// 执行并返回DataReader
        /// </summary>
        /// <returns></returns>
        public DbDataReader ExecuteDataReader()
        {
            return this.ConnnectDB<DbDataReader>(new Func<DbDataReader>(ExecuteDataReaderCallBlack));

        }

        /// <summary>
        /// 执行并返回DataReader
        /// </summary>
        /// <returns></returns>
        private DbDataReader ExecuteDataReaderCallBlack()
        {
            return dbCommand_0.ExecuteReader();

        }


        public List<T> DataReaderFillList<T>(DbDataReader dbDataReader) where T : class, new()
        {
            List<T> result;


            Delegate0 @delegate = typeof(T).smethod_0(true).method_0();
            if (@delegate == null)
            {
                List<T> list = new List<T>(this.ListIniCapacity);
                Class9 class9_ = new Class9(dbDataReader);
                while (dbDataReader.Read())
                {
                    T t = Activator.CreateInstance(typeof(T)) as T;
                    Class30.smethod_2(class9_, t);
                    list.Add(t);
                }
                result = list;
            }
            else
            {
                result = (List<T>)@delegate(Class28.int_2, dbDataReader, this.ListIniCapacity);
            }

            return result;
        }



        public List<T> FillScalarList<T>()
        {
            return this.ConnnectDB<List<T>>(new Func<List<T>>(this.method_14<T>));
        }

        public DataTable FillDataTable()
        {
            return this.ConnnectDB<DataTable>(new Func<DataTable>(this.method_15));
        }

        public DataSet FillDataSet(params string[] tableNames)
        {
            DbContext.Class5 @class = new DbContext.Class5();
            @class.string_0 = tableNames;
            @class.dbContext_0 = this;
            return this.ConnnectDB<DataSet>(new Func<DataSet>(@class.method_0));
        }

        public List<T> FillList<T>() where T : class, new()
        {
            typeof(T).Assertion_Model();
            return this.ConnnectDB<List<T>>(new Func<List<T>>(this.DataReaderFillList<T>));
        }

        public T GetDataItem<T>() where T : class, new()
        {
            typeof(T).Assertion_Model();
            return this.ConnnectDB<T>(new Func<T>(this.method_17<T>));
        }

        public T CreateHolder<T>() where T : class, IDbContextHolder, new()
        {
            T result = Activator.CreateInstance(typeof(T)) as T;
            result.DbContext = this;
            return result;
        }

        [CompilerGenerated]
        private int method_12()
        {
            return this.dbCommand_0.ExecuteNonQuery();
        }

        [CompilerGenerated]
        private object method_13()
        {
            return this.dbCommand_0.ExecuteScalar();
        }

        [CompilerGenerated]
        private List<T> method_14<T>()
        {
            List<T> list = new List<T>(DbContextDefaultSetting.ListResultCapacity);
            using (DbDataReader dbDataReader = this.dbCommand_0.ExecuteReader())
            {
                while (dbDataReader.Read())
                {
                    list.Add(DbHelper.smethod_5<T>(dbDataReader.GetValue(0)));
                }
                dbDataReader.Close();
            }
            return list;
        }

        [CompilerGenerated]
        private DataTable method_15()
        {
            DataTable dataTable = new DataTable();
            try
            {

                using (DbDataReader dbDataReader = this.dbCommand_0.ExecuteReader())
                {
                    for (int i = 0; i < dbDataReader.FieldCount; i++)
                    {
                        DataColumn myDataColumn = new DataColumn();
                        myDataColumn.DataType = dbDataReader.GetFieldType(i);
                        myDataColumn.ColumnName = dbDataReader.GetName(i);
                        dataTable.Columns.Add(myDataColumn);
                    }

                    ///添加表的数据
                    while (dbDataReader.Read())
                    {
                        DataRow myDataRow = dataTable.NewRow();
                        for (int i = 0; i < dbDataReader.FieldCount; i++)
                        {
                            myDataRow[i] = dbDataReader[i];
                        }
                        dataTable.Rows.Add(myDataRow);
                        myDataRow = null;
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return dataTable;
        }

        [CompilerGenerated]
        private List<T> DataReaderFillList<T>() where T : class, new()
        {
            List<T> result;
            using (DbDataReader dbDataReader = this.dbCommand_0.ExecuteReader())
            {
                Delegate0 @delegate = typeof(T).smethod_0(true).method_0();
                if (@delegate == null)
                {
                    List<T> list = new List<T>(this.ListIniCapacity);
                    Class9 class9_ = new Class9(dbDataReader);
                    while (dbDataReader.Read())
                    {
                        T t = Activator.CreateInstance(typeof(T)) as T;
                        Class30.smethod_2(class9_, t);
                        list.Add(t);
                    }
                    dbDataReader.Close();
                    result = list;
                }
                else
                {
                    result = (List<T>)@delegate(Class28.int_2, dbDataReader, this.ListIniCapacity);
                }
            }
            return result;
        }

        [CompilerGenerated]
        private T method_17<T>() where T : class, new()
        {
            T result;
            using (DbDataReader dbDataReader = this.dbCommand_0.ExecuteReader(CommandBehavior.SingleRow))
            {
                Delegate0 @delegate = typeof(T).smethod_0(true).method_0();
                if (@delegate == null)
                {
                    T t = default(T);
                    Class9 class9_ = new Class9(dbDataReader);
                    if (dbDataReader.Read())
                    {
                        t = (Activator.CreateInstance(typeof(T)) as T);
                        Class30.smethod_2(class9_, t);
                    }
                    dbDataReader.Close();
                    result = t;
                }
                else
                {
                    result = (T)((object)@delegate(Class28.int_0, dbDataReader, 1));
                }
            }
            return result;
        }

        private static object objLock = new object();
        public void WriteLog(string text)
        {
            lock (objLock)
            {
                string path = AppDomain.CurrentDomain.BaseDirectory + "dbLog";

                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                DateTime currentTime = DateTime.Now;

                path += @"\" + currentTime.ToString("yyyy-MM-dd") + ".txt";

                if (File.Exists(path))
                {
                    using (StreamWriter sw = File.AppendText(path))
                    {
                        sw.Write(Environment.NewLine + Environment.NewLine + currentTime.ToString("yyyy-MM-dd") + " ------ " + text);
                    }
                }
                else
                {
                    using (StreamWriter sw = File.CreateText(path))
                    {
                        sw.Write(currentTime.ToString("yyyy-MM-dd") + " ------ " + text);
                    }
                }
            }

        }
    }
}
